package com.flyduck.annotation.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.flyduck.annotation.annotation.DbFieldProperty;
import com.flyduck.annotation.annotation.HeaderValidAspect;
import com.flyduck.annotation.annotation.HeaderValidInterceptor;
import com.flyduck.annotation.config.WebConfig;
import com.flyduck.annotation.entity.AutoUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

/**
 * <p></p>
 *
 * @author flyduck 2020/10/22 21:49
 * @version V1.0
 * @modify by user: flyduck 2020/10/22
 * @modify by reason:{原因}
 **/
@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private WebConfig webConfig;

    private final static String KEY_FIELD = "field";
    private final static String KEY_NAME = "name";
    private final static String KEY_TYPE = "type";
    private final static String KEY_PROPERTY = "property";

    private Map<String, Map<String, Object>> getFieldMap(Class clazz) {
        List<Field> tempFieldList = new ArrayList();

        for(Class tempClass = clazz; tempClass != null; tempClass = tempClass.getSuperclass()) {
            Collections.addAll(tempFieldList, tempClass.getDeclaredFields());
        }

        Map<String, Map<String, Object>> fieldMap = new HashMap<>();

        for (Field field : tempFieldList) {
            Map<String, Object> propertyMap = new HashMap<>();
            String fieldValue = field.getName().toLowerCase();

            propertyMap.put(KEY_PROPERTY, field.getName());

            DbFieldProperty fieldProperty = field.getAnnotation(DbFieldProperty.class);
            if (fieldProperty != null) {
                if (!StringUtils.isEmpty(fieldProperty.value())) {
                    fieldValue = fieldProperty.value().toLowerCase();
                }
                propertyMap.put(KEY_NAME, fieldProperty.name());
                propertyMap.put(KEY_TYPE, fieldProperty.clazz());
            }
            propertyMap.put(KEY_FIELD, fieldValue);

            fieldMap.put(fieldValue, propertyMap);
        }

        return fieldMap;
    }

    private <T> T buildObject(Class clazz, Map<String, Object> data, Map<String, Map<String, Object>> fieldMap) throws IllegalAccessException, InstantiationException {
        Map<String, Object> map = new HashMap();
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            Map<String, Object> propertyMap = fieldMap.get(entry.getKey());
            if (propertyMap != null) {
                Object value = entry.getValue();
                Class propertyClazz = (Class) propertyMap.get(KEY_TYPE);
                if (value != null && propertyClazz != null && !propertyClazz.equals(Object.class)) {
                    Object finalValue = propertyClazz.cast(value);
                    map.put(propertyMap.get(KEY_PROPERTY).toString(), finalValue);
                } else {
                    map.put(propertyMap.get(KEY_PROPERTY).toString(), value);
                }
            }
        }
        Object resultModel = clazz.newInstance();
        BeanMap.create(resultModel).putAll(map);
        return (T) resultModel;
    }

    @GetMapping("validInterceptor")
    @HeaderValidInterceptor("ADMIN")
    public String validInterceptor() {
        return "pass";
    }

    @GetMapping("noNeedValid")
    public String noNeedValid() {
        return "pass";
    }

    @GetMapping("validAspect")
    @HeaderValidAspect("ADMIN")
    public String validAspect() {
        return "pass";
    }

    @GetMapping("list")
    public String listUser() {
        String result = "";

        try {
            Class.forName(webConfig.getDbDriver());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        try (Connection c = DriverManager.getConnection(webConfig.getDbUrl(), webConfig.getDbUsername(), webConfig.getDbPassword());
             Statement s = c.createStatement();) {

            String sql = "select * from flyduck_user limit 10";

            Map<String, Map<String, Object>> fieldMap = getFieldMap(AutoUser.class);


            // 执行查询语句，并把结果集返回给ResultSet
            ResultSet rs = s.executeQuery(sql);
            ResultSetMetaData resultSetMetaData = rs.getMetaData();
            List<Map<String, Object>> list = new ArrayList<>();
            List<AutoUser> userList = new ArrayList<>();
            while (rs.next()) {
                Map<String, Object> row = new HashMap<>();
                for (int index = 1; index <= resultSetMetaData.getColumnCount(); index++) {
                    row.put(resultSetMetaData.getColumnName(index).toLowerCase(), rs.getObject(index));
                }
                list.add(row);

                AutoUser user = buildObject(AutoUser.class, row, fieldMap);
                userList.add(user);
            }

            result = objectMapper.writeValueAsString(userList);

        } catch (Exception e) {
            // TODO 异常处理
        }

        return result;
    }
}
